package com.syh.jn.scm.infrastructure.repository.impl.downstream.purchase;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.util.validator.ValidationUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.core.expction.DataModelException;
import com.syh.jn.scm.domain.downstream.entity.purchase.DownPurchaseReturnOrder;
import com.syh.jn.scm.domain.downstream.entity.purchase.DownPurchaseReturnOrderItem;
import com.syh.jn.scm.domain.downstream.repository.purchase.DownPurchaseReturnOrderRepository;
import com.syh.jn.scm.dto.downstream.purchase.DownPurchaseReturnOrderItemVo;
import com.syh.jn.scm.dto.downstream.purchase.DownPurchaseReturnOrderVo;
import com.syh.jn.scm.exception.BusinessException;
import com.syh.jn.scm.infrastructure.repository.model.base.DictModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsBrandModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsCategoryModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsModel;
import com.syh.jn.scm.infrastructure.repository.model.sale.SaleOrderModel;
import com.syh.jn.scm.infrastructure.repository.model.sale.SaleReturnOrderItemModel;
import com.syh.jn.scm.infrastructure.repository.model.sale.SaleReturnOrderModel;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import org.apache.ibatis.jdbc.SQL;
import org.hibernate.Query;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Date:2018/7/9
 * Author:Clown
 * 下游采购退货仓储实现;
 */
@Repository
public class DownPurchaseReturnOrderRepositoryImpl extends AbstractAggregateRepository<DownPurchaseReturnOrder, SaleReturnOrderModel, Long> implements DownPurchaseReturnOrderRepository {

  @Override
  public Long add(DownPurchaseReturnOrder downPurchaseReturnOrder) {
    Long id = super.add(downPurchaseReturnOrder);
    this.saveOrderItems(id, downPurchaseReturnOrder.getItems());
    return id;
  }

  /**
   * 修改订单主体加明细
   *
   * @param downPurchaseReturnOrder
   */
  @Override
  public void update(DownPurchaseReturnOrder downPurchaseReturnOrder) {
    super.update(downPurchaseReturnOrder);
    this.removeItem(downPurchaseReturnOrder);
    this.saveOrderItems(downPurchaseReturnOrder.getId(), downPurchaseReturnOrder.getItems());
  }

  @Override
  public DownPurchaseReturnOrder getById(Long id) {
    DownPurchaseReturnOrder order = super.getById(id);
    if (order == null) {
      return order;
    }
    order.setItems(this.getItemsByReturnOrderId(id));
    return order;
  }

  @Override
  public DownPurchaseReturnOrderVo getKeyView(Serializable key) {
    DownPurchaseReturnOrderVo vo = super.getKeyView(key);
    if(vo == null)
      throw new BusinessException("数据异常，采购退货单不存在");
    vo.setItems(transformPurchaseReturn(this.getItemsByReturnOrderId(vo.getId())));
    return vo;
  }

  /**
   * 修改订单状态
   *
   * @param downPurchaseReturnOrder
   */
  public void updateStatus(DownPurchaseReturnOrder downPurchaseReturnOrder) {
    super.update(downPurchaseReturnOrder);
  }

  /**
   * 删除采购退货单
   *
   * @param downPurchaseReturnOrder
   */
  @Override
  public void remove(DownPurchaseReturnOrder downPurchaseReturnOrder) {
    //删除主体
    super.removeById(downPurchaseReturnOrder.getId());
    //删除明细
    this.removeItem(downPurchaseReturnOrder);
  }

  /**
   * 保存订单项方法
   *
   * @param saleReturnOrderId
   * @param items
   */
  private void saveOrderItems(Long saleReturnOrderId, List<DownPurchaseReturnOrderItem> items) {
    items.stream().forEach(item -> {
      SaleReturnOrderItemModel itemModel = new SaleReturnOrderItemModel();

      GoodsModel goodsModel = this.hibernateTemplate.get(GoodsModel.class, item.getGoodsId());
      GoodsBrandModel goodsBrandModel = new GoodsBrandModel();
      if (goodsModel.getGoodsBrandId() != null) {
        goodsBrandModel = this.hibernateTemplate.get(GoodsBrandModel.class, goodsModel.getGoodsBrandId());
      }
      GoodsCategoryModel goodsCategoryModel = new GoodsCategoryModel();
      if (goodsModel.getCategoryId() != null) {
        goodsCategoryModel = this.hibernateTemplate.get(GoodsCategoryModel.class, goodsModel.getCategoryId());
      }

      SaleReturnOrderModel saleReturnOrderModel = this.hibernateTemplate.get(SaleReturnOrderModel.class, saleReturnOrderId);

      ExtBeanUtils.copyProperties(item, itemModel);
      itemModel.setSaleReturnOrderId(saleReturnOrderId);
      itemModel.setBusinessEntityId(saleReturnOrderModel.getBusinessEntityId());

      //在仓储层冗余是为了安全和数据的准确
      itemModel.setGoodsName(goodsModel.getName());
      itemModel.setSpecName(goodsModel.getSpecName());
      itemModel.setGoodsCode(goodsModel.getCode());
      itemModel.setIsDefaultGoods(goodsModel.getIsDefaultGoods());
      itemModel.setConversionRate(goodsModel.getConversionRate());
      itemModel.setCodeBar(goodsModel.getCodeBar());
      itemModel.setUnits(goodsModel.getUnits());
      itemModel.setCategoryId(goodsModel.getCategoryId());
      itemModel.setCategoryName(goodsCategoryModel.getName());
      itemModel.setCategoryCatalogCode(goodsCategoryModel.getCatalogCode());
      itemModel.setBrandId(ExtStringUtils.isBlank(goodsModel.getGoodsBrandId()) ? null : goodsModel.getGoodsBrandId());
      itemModel.setBrandName(ExtStringUtils.isBlank(goodsBrandModel.getName()) ? null : goodsBrandModel.getName());
      this.hibernateTemplate.save(itemModel);
    });
  }

  /**
   * 删除订单项
   *
   * @param order
   */
  private void removeItem(DownPurchaseReturnOrder order) {
    StringBuffer hql = new StringBuffer();
    hql.append("from SaleReturnOrderItemModel model where model.saleReturnOrderId = ?");
    List<SaleReturnOrderItemModel> itemModelList = (List<SaleReturnOrderItemModel>) this.hibernateTemplate.find(hql.toString(), order.getId());
    itemModelList.stream().forEach(item -> {
      this.hibernateTemplate.delete(item);
    });
  }

  /**
   * 上传单据图片
   *
   * @param order
   */
  @Override
  public void upload(DownPurchaseReturnOrder order) {
    super.update(order);
  }

  /**
   * 根据id查出明细
   *
   * @param id
   * @return
   */
  @Override
  public List<DownPurchaseReturnOrderItem> getItemsByReturnOrderId(Long id) {
    ExtAssert.notNull(id, "id为空");
    String hql = "from SaleReturnOrderItemModel model where model.saleReturnOrderId = ?";
    List<SaleReturnOrderItemModel> itemModelList = (List<SaleReturnOrderItemModel>) this.hibernateTemplate.find(hql.toString(), id);
    List<DownPurchaseReturnOrderItem> itemList = new ArrayList<>();
    itemModelList.stream().forEach(item -> {
      DownPurchaseReturnOrderItem orderItem = new DownPurchaseReturnOrderItem();
      ExtBeanUtils.copyProperties(item, orderItem);
      itemList.add(orderItem);
    });
    return itemList;
  }

  /**
   * 根据归属id获取明细(订单导出用)
   *
   * @param returnOrderIds
   * @return
   */
  @Override
  public List<DownPurchaseReturnOrderItemVo> getItemsByPurchaseReturnOrderIds(Long[] returnOrderIds) {
    String hql = "from SaleReturnOrderItemModel model where model.saleReturnOrderId in (:returnOrderIds)";

    Query query = buildQuery(hql);
    query.setParameterList("returnOrderIds", returnOrderIds);
    List<SaleReturnOrderItemModel> itemModelList = query.list();
    List<DownPurchaseReturnOrderItem> itemList = new ArrayList<>();
    itemModelList.stream().forEach(item -> {
      DownPurchaseReturnOrderItem orderItem = new DownPurchaseReturnOrderItem();
      ExtBeanUtils.copyProperties(item, orderItem);
      itemList.add(orderItem);
    });
    return transformPurchaseReturn(itemList);
  }

  @Override
  public void cancel(DownPurchaseReturnOrder purchaseReturnOrder) {
    super.update(purchaseReturnOrder);
  }

  @Override
  public void updateOrderAndItems(DownPurchaseReturnOrder order) {
    SaleReturnOrderModel orderModel = this.hibernateTemplate.get(SaleReturnOrderModel.class, order.getId());
    if(orderModel == null){
      throw new DataModelException("订单不存在");
    }
    ExtBeanUtils.copyProperties(order, orderModel);
    this.hibernateTemplate.update(orderModel);
    //更新订单项
    order.getItems().forEach(orderItem -> {
      SaleReturnOrderItemModel model = this.hibernateTemplate.get(SaleReturnOrderItemModel.class, orderItem.getId());
      if(model == null){
        throw new DataModelException("对应明细不存在");
      }
      ExtBeanUtils.copyProperties(orderItem, model);
      this.hibernateTemplate.update(model);
    });
  }


  @Override
  protected SQL getViewSql() {

    //model数组
    Class[] classes = {
            SaleReturnOrderModel.class,
            DictModel.class,
            SaleOrderModel.class
    };
    //别名数组
    String[] aliases = {
            "saleReturnOrder",
            "dict",
            "saleOrder"
    };


    return new SQL() {{

      SELECT(SQLAliasGenerateUtil.aliasGenerate(classes, aliases, null),
              "dict.NAME AS returnReasonName,saleOrder.CODE AS saleOrderCode,supplier.NAME AS supplierName"
      );
      FROM("T_SALE_RETURN_ORDER saleReturnOrder");
      LEFT_OUTER_JOIN("T_BASE_DICT dict on saleReturnOrder.RETURN_REASON_ID = dict.ID", "T_BASE_SUPPLIER supplier on saleReturnOrder.BUSINESS_ENTITY_ID = supplier.ID", "T_SALE_ORDER saleOrder on saleReturnOrder.SALE_ORDER_ID = saleOrder.ID");
    }};
  }

  @Override
  protected Class getViewObject() {
    return DownPurchaseReturnOrderVo.class;
  }

  @Override
  protected BaseResolve getViewWrapperResolve(Wrapper wrapper) {
    Map<String, String> params = new HashMap<>();
    params.put("id", "saleReturnOrder.ID");
    params.put("downStreamCompanyId", "saleReturnOrder.DOWN_STREAM_COMPANY_ID");
    params.put("code", "saleReturnOrder.CODE");
    params.put("createType", "saleReturnOrder.CREATE_TYPE");
    params.put("saleOrderCode", "saleOrder.CODE");
    params.put("returnOrdState", "saleReturnOrder.RETURN_ORD_STATE");
    params.put("createTimeStamp", "saleReturnOrder.CREATE_TIME_STAMP");
    params.put("statementId", "saleReturnOrder.STATEMENT_ID");
    params.put("deliveryState", "saleReturnOrder.DELIVERY_STATE");
    params.put("collectState", "saleReturnOrder.COLLECT_STATE");
    params.put("inputDateTimestamp", "saleReturnOrder.INPUT_DATE_TIMESTAMP");
    ResolveToSQL parse = new ResolveToSQL(wrapper, (propertyName) -> {
      return params.get(propertyName);
    });
    return parse;
  }

  /**
   * 内部方法  业务模型转传输对象
   *
   * @param entityList
   * @return
   */
  private List<DownPurchaseReturnOrderItemVo> transformPurchaseReturn(List<DownPurchaseReturnOrderItem> entityList) {
    List<DownPurchaseReturnOrderItemVo> voList = new ArrayList<>();
    entityList.stream().forEach((entity) -> {
      DownPurchaseReturnOrderItemVo vo = new DownPurchaseReturnOrderItemVo();
      ExtBeanUtils.copyProperties(entity, vo);
      voList.add(vo);
    });
    return voList;
  }
}

